package com.iot08.api.service.supplement;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iot08.api.config.properties.CommonProperties;
import com.iot08.api.constant.Constant;
import com.iot08.api.service.*;
import com.iot08.api.utils.StringTool;
import com.iot08.api.utils.alipay.AlipayUtil;
import com.iot08.api.utils.applepay.ApplePayUtil;
import com.iot08.api.utils.wxpay.AmountUtils;
import com.iot08.api.utils.wxpay.WeChatPayUtils;
import com.iot08.api.utils.wxpay.WxPayUtil;
import com.iot08.api.utils.wxpay.XMLUtil;
import com.iot08.api.vo.request.*;
import com.iot08.apple.pay.model.*;
import com.iot08.common.constant.Const;
import com.iot08.common.entity.app.*;
import com.iot08.common.utils.DateUtil;
import com.iot08.common.utils.StringUtil;
import com.iot08.common.utils.response.ResponseEnum;
import com.iot08.common.utils.response.ResponseMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @version 1.0
 * @Description:
 * @author: Rock
 * @time: 2021/2/27 9:11
 */
@Slf4j
@Service
public class PayService {

    @Resource
    private PaymentService paymentService;
    @Resource
    private CommonProperties commonProperties;
    @Resource
    private DeviceService deviceService;
    @Resource
    private AlipayUtil alipayUtil;
    @Resource
    private WxPayUtil wxPayUtil;

    @Resource
    private ApplePayUtil applePayUtil;

    @Resource
    private PayOrderInfoService payOrderInfoService;
    @Resource
    private AliPayNotifyInfoService aliPayNotifyInfoService;
    @Resource
    private VipMemberService vipMemberService;

    @Resource
    private ProductInfoService productInfoService;

    @Resource
    private WechatPayNotifyInfoService wechatPayNotifyInfoService;

    @Resource
    private ApplePayNotifyInfoService applePayNotifyInfoService;

    @Resource
    private RefundApplyService refundApplyService;

    @Resource
    private GoldCoinService goldCoinService;

    @Resource
    private UserGoldCoinService userGoldCoinService;

    @Resource
    private BrokenScreenInsuranceService brokenScreenInsuranceService;


    @Value("${domain}")
    private String domaim;

    @Value("${pay.call.back.notify.request.way}")
    private String callBackNotifyRequestWay;

    @Value("${support.discount.lowest.version}")
    private String supportDiscountLowestVersion;

    private int orderIdJuphoon = 40;

    // 支付宝支付异步通知校验成功返回字符串
    private static final String alipayNotifySuccess = "success";

    private static final String alipayNotifyFail = "fail";

    private static final String SUCCESS = "SUCCESS";

    private static final String FAIL = "FAIL";



    /**
     * @param imei
     * @param vo
     * @time: 2021/2/27 9:13
     * @author: Rock
     * @version 1.0
     */
    public ResponseMap getPayment(String imei, GetPaymentReqVO vo, String ipAddr) throws Exception {
        ResponseMap res = ResponseMap.success();
        String subject = "";
        BigDecimal price = new BigDecimal(0.01);
        if (StringUtil.isNumeric(vo.getOrderid())) {
            if (Integer.parseInt(vo.getOrderid()) == orderIdJuphoon) {
                Device device = deviceService.findById(imei);
                if (device == null) {
                    log.error("Deivce is null. imei={}", imei);
                    return ResponseMap.fail(ResponseEnum.STATUS2001.getCode(), ResponseEnum.STATUS2001.getMsg(), imei);
                }
                if (Const.INT_1.equals(device.getVideoPermanent())) {
                    return ResponseMap.fail(ResponseEnum.STATUS403.getCode(), "获取订单失败,已经开通了永久套餐,请返回刷新");
                }
                price = new BigDecimal(commonProperties.getJuphoon().get(0).get("price").toString());
                subject = "永久开通视频服务功能";
            } else if (commonProperties.getRenew().size() > Integer.parseInt(vo.getOrderid())) {
                Map<String, Object> tempMap = commonProperties.getRenew().get(Integer.parseInt(vo.getOrderid()));
                price = new BigDecimal(tempMap.get("price").toString());
                subject = String.format("视频通话%s分钟", tempMap.get("minute"));
            } else {
                log.error("param orderid is Exception. vo={}", vo.toString());
                return ResponseMap.fail(ResponseEnum.STATUS400.getMsg());
            }
        } else {
            log.error("param orderid is Exception. vo={}", vo.toString());
            return ResponseMap.fail(ResponseEnum.STATUS400.getMsg());
        }
        String outTradeNo = UUID.randomUUID().toString().replaceAll("-", "");
        if ("wechat".equals(vo.getType())) {
            String notifyUrl = String.format(callBackNotifyRequestWay,"://%s/getway/accounts/wx_payment", domaim);
            String monty = AmountUtils.changeY2F(price.toString());
            wxPayUtil.getAppPrepayId(subject, outTradeNo, monty, ipAddr, notifyUrl, res);
        } else if ("alipay".equals(vo.getType())) {
            String notifyUrl = String.format(callBackNotifyRequestWay,"://%s/getway/accounts/alipay_payment", domaim);
            String order = alipayUtil.createSignDataStr(subject, subject, price.toString(), outTradeNo, notifyUrl);
            res.put("order_string", order);
        } else {
            log.error("param type is Exception. vo={}", vo.toString());
            return ResponseMap.fail();
        }
        //添加支付记录
        paymentService.add(imei, vo.getOpenid(), vo.getType(), vo.getOrderid(), outTradeNo);
        return res;
    }


    /**
     * @description 创建支付信息
     * @author cwj
     * @param [vo, ipAddr]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/12/29 18:24
     **/
    public ResponseMap createPaymentInfo(CreatePaymentReqBodyFormVO vo, String ipAddr) throws Exception {
        //查询产品信息
        ProductInfo productInfo = productInfoService.findById(new ObjectId(vo.getPid()));
        //查询用户是否已经购买永久会员，如果已经购买，提醒用户无需在次购买
        VipMember vipMember = vipMemberService.queryVipMemberByOpenid(vo.getOpenid());
        if(ObjectUtils.isNotEmpty(vipMember) && vipMember.getType().equals(3)){
            return ResponseMap.fail("您已经购买永久会员，无需再购买会员");
        }
        if(ObjectUtils.isEmpty(vo.getPayAmount())) {
            vo.setPayAmount(productInfo.getPrice());
        }
        if(ObjectUtils.isEmpty(productInfo)) {
            return ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.payment.product.notExists");
        }
        /*if(productInfo.getCurrency().equals(vo.getCurrency()) && (!productInfo.getPrice().equals(vo.getPayAmount()) || !productInfo.getOriginalPrice().equals(vo.getOriginalCost()))){
            return ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.payment.product.price.error");
        }*/
        ResponseMap res = ResponseMap.success();
        String appAccountToken = UUID.randomUUID().toString();
        //获取版本信息
        VersionVo versionVo = obtainVersionInfo(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
        //检查是否是androw的高版本（支持折扣的版本）
        boolean isAndrowHighVerison = isAndrowHighVersion(versionVo.getUserAgent(), versionVo.getVersion());
        //检查是否有折扣，微信和支付宝支付如果有折扣且当前时间段在折扣区间内则按照折扣后的价格计算
        boolean isDisCountExists = checkDiscountExists(productInfo.getDiscount(),productInfo.getDiscountStartTime(),productInfo.getDiscountEndTime());
        //创建支付订单
        String orderId = createPayOrder(vo, ipAddr, isAndrowHighVerison, isDisCountExists, productInfo, appAccountToken);
        //返回订单id
        res.put("orderid",orderId);
        if(StringUtils.isNotEmpty(orderId)){
            //创建或更新会员
            vipMemberService.createOrUpdateVipMember(vo, productInfo.getType(),orderId);
            String subject = "购买App会员";
            if ("wechatPay".equals(vo.getPayType())) {
                String notifyUrl = String.format("%s://%s/getway/accounts/wx_payment",callBackNotifyRequestWay, domaim);
                BigDecimal amount = productInfo.getPrice();
                if(isAndrowHighVerison && isDisCountExists) {
                    amount = amount.multiply(productInfo.getDiscount());
                }
                amount = amount.multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN);
                JSONObject jsonObject= wxPayUtil.unifiedOrder(orderId,subject,amount.intValue(),notifyUrl,ipAddr);
                if(ObjectUtils.isEmpty(jsonObject)) {
                    return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.response.wxpayment.order.fail");
                }
                //返回支付所需参数
                res.put("wechatPaymentParams",jsonObject);
            } else if ("alipay".equals(vo.getPayType())) {
                String notifyUrl = String.format("%s://%s/getway/accounts/alipay_payment", callBackNotifyRequestWay,domaim);
                BigDecimal amount = productInfo.getPrice();
                if(isAndrowHighVerison && isDisCountExists) {
                    amount = amount.multiply(productInfo.getDiscount()).setScale(2,RoundingMode.DOWN);
                }
                String paymentParam = alipayUtil.createSignDataStr(subject, subject, amount.toString(), orderId, notifyUrl);
                if(StringUtils.isEmpty(paymentParam)){
                    return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.response.alipayment.order.fail");
                }
                res.put("alipayPaymentParams", paymentParam);
            } else if("applePay".equals(vo.getPayType())){
                log.info("Apple pay支付订单已经生成");
                res.put("appAccountToken",appAccountToken);
            } else {
                log.error("param type is Exception. vo={}", vo);
                return ResponseMap.fail();
            }
        }else {
            log.error("产品订单创建失败.......");
            return ResponseMap.fail("支付订单创建失败");
        }
        return res;
    }

    /**
     * @description 创建会员支付订单
     * @author cwj
     * @param [vo, ipAddr, isAndrowHighVerison, isDisCountExists, productInfo, appAccountToken]
     * @return java.lang.String
     * @date @time 2025/3/8 10:19
     **/
    private String createPayOrder(CreatePaymentReqBodyFormVO vo, String ipAddr, boolean isAndrowHighVerison, boolean isDisCountExists, ProductInfo productInfo, String appAccountToken) {
        String orderId = "";
        if(isAndrowHighVerison && isDisCountExists){
            BigDecimal amount = productInfo.getPrice().multiply(productInfo.getDiscount()).setScale(2,RoundingMode.DOWN);
            orderId = payOrderInfoService.createPayOrderInfo(vo, productInfo,amount, ipAddr, appAccountToken,0);
        } else {
            //创建会员商品订单支付记录
            orderId = payOrderInfoService.createPayOrderInfo(vo, productInfo, productInfo.getPrice(), ipAddr, appAccountToken,0);
        }
        return orderId;
    }

    /**
     * @description 创建金币支付订单
     * @author cwj
     * @param [vo, ipAddr]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/3/6 11:34
     **/
    public ResponseMap createGoldCoinPaymentInfo(CreateGoldCoinPaymentReqBodyFormVO vo, String ipAddr) throws Exception {
        //查询
        GoldCoinProductInfo goldCoinProductInfo = goldCoinService.findById(new ObjectId(vo.getGid()));
        if(ObjectUtils.isEmpty(goldCoinProductInfo)) {
            return ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.payment.goldCoin.notExists");
        }
        ResponseMap res = ResponseMap.success();
        String appAccountToken = UUID.randomUUID().toString();
        VipMember vipMember = vipMemberService.queryVipMemberByOpenid(vo.getOpenid());
        //获取版本信息
        VersionVo versionVo = obtainVersionInfo(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
        //检查是否是androw的高版本（支持折扣的版本）
        boolean isAndrowHighVerison = isAndrowHighVersion(versionVo.getUserAgent(), versionVo.getVersion());
        //检查是否有折扣，微信和支付宝支付如果有折扣且当前时间段在折扣区间内则按照折扣后的价格计算
        boolean isDisCountExists = checkDiscountExists(goldCoinProductInfo.getDiscount(),goldCoinProductInfo.getDiscountStartTime(),goldCoinProductInfo.getDiscountEndTime());
        ProductInfo productInfo = null;
        if(!ObjectUtils.isEmpty(vipMember) && StringUtils.isNotEmpty(vipMember.getPId())) {
            productInfo = productInfoService.findById(new ObjectId(vipMember.getPId()));
        }
        String orderId = createGoldCoinPayOrder(vo,vipMember, ipAddr, isAndrowHighVerison, isDisCountExists, goldCoinProductInfo, appAccountToken,productInfo);
        //是会员且不是免费会员
        boolean isVipMember = !ObjectUtils.isEmpty(vipMember) && vipMember.getIsOnTrialVip().equals(0);
        //返回订单id
        res.put("orderid",orderId);
        if(StringUtils.isNotEmpty(orderId)){
            //创建或更新用户金币信息
            userGoldCoinService.createOrUpdateUserGoldCoin(vo,goldCoinProductInfo,orderId);
            String subject = "购买金币";
            if ("wechatPay".equals(vo.getPayType())) {
                String notifyUrl = String.format("%s://%s/getway/accounts/wx_payment",callBackNotifyRequestWay, domaim);
                //获取打折后的实际支付的金额
                BigDecimal amount = calculateAmount(goldCoinProductInfo, isVipMember, isAndrowHighVerison, isDisCountExists, productInfo, vipMember,vo.getPayType());
                amount = amount.multiply(new BigDecimal(100)).setScale(0, RoundingMode.DOWN);
                JSONObject jsonObject= wxPayUtil.unifiedOrder(orderId,subject,amount.intValue(),notifyUrl,ipAddr);
                if(ObjectUtils.isEmpty(jsonObject)) {
                    return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.response.wxpayment.order.fail");
                }
                //返回支付所需参数
                res.put("wechatPaymentParams",jsonObject);
            } else if ("alipay".equals(vo.getPayType())) {
                String notifyUrl = String.format("%s://%s/getway/accounts/alipay_payment", callBackNotifyRequestWay,domaim);
                //获取打折后实际支付的金额
                BigDecimal amount = calculateAmount(goldCoinProductInfo, isVipMember, isAndrowHighVerison, isDisCountExists, productInfo, vipMember,vo.getPayType());
                String paymentParam = alipayUtil.createSignDataStr(subject, subject, amount.toString(), orderId, notifyUrl);
                if(StringUtils.isEmpty(paymentParam)){
                    return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.response.alipayment.order.fail");
                }
                res.put("alipayPaymentParams", paymentParam);
            } else if("applePay".equals(vo.getPayType())){
                log.info("Apple pay支付订单已经生成");
                res.put("appAccountToken",appAccountToken);
            } else {
                log.error("param type is Exception. vo={}", vo);
                return ResponseMap.fail();
            }
        }else {
            log.error("金币产品订单创建失败.......");
            return ResponseMap.fail("支付订单创建失败");
        }
        return res;
    }

    /**
     * @description 根据业务计算打折后实际需要支付的金额
     * @author cwj
     * @param [goldCoinProductInfo, isVipMember, isAndrowHighVerison, isDisCountExists, productInfo, vipMember]
     * @return java.math.BigDecimal
     * @date @time 2025/4/1 10:51
     **/
    private BigDecimal calculateAmount(GoldCoinProductInfo goldCoinProductInfo, boolean isVipMember, boolean isAndrowHighVerison, boolean isDisCountExists,
                                       ProductInfo productInfo, VipMember vipMember ,String payType) {
        BigDecimal amount = goldCoinProductInfo.getPrice();
        if(!"applePay".equals(payType)) {
            if (!isVipMember && isAndrowHighVerison && isDisCountExists) {
                //苹果支付没有折扣
                amount = amount.multiply(goldCoinProductInfo.getDiscount()).setScale(2, RoundingMode.DOWN);
            } else if (isVipMember) {
                //苹果支付没有折扣，计算会员折扣
                amount = goldCoinProductInfo.getPrice().multiply(ObjectUtils.isNotEmpty(productInfo) && ObjectUtils.isNotEmpty(productInfo.getPayGoldCoinDiscount()) ?
                        productInfo.getPayGoldCoinDiscount() : transferVipTypeToDiscount(vipMember.getType())).setScale(2, RoundingMode.DOWN);
            }
        }
        return amount;
    }

    /**
     * @description 创建金币支付订单
     * @author cwj
     * @param [vo, ipAddr, isAndrowHighVerison, isDisCountExists, goldCoinProductInfo, appAccountToken]
     * @return java.lang.String
     * @date @time 2025/3/8 11:05
     **/
    private String createGoldCoinPayOrder(CreateGoldCoinPaymentReqBodyFormVO vo,VipMember vipMember, String ipAddr, boolean isAndrowHighVerison,
                                          boolean isDisCountExists, GoldCoinProductInfo goldCoinProductInfo, String appAccountToken,ProductInfo productInfo) {
        String orderId = "";
        //检查是否为非试用期的会员
        boolean isVipMember = !ObjectUtils.isEmpty(vipMember) && vipMember.getIsOnTrialVip().equals(0);
        BigDecimal payAmount = goldCoinProductInfo.getPrice();
        if(!isVipMember && isAndrowHighVerison && isDisCountExists) {
            //苹果支付没有折扣
            if(!"applePay".equals(vo.getPayType())) {
                 payAmount = goldCoinProductInfo.getPrice().multiply(goldCoinProductInfo.getDiscount()).setScale(2,RoundingMode.DOWN);
            }
            //创建会员商品订单支付记录
            orderId = payOrderInfoService.createGoldCoinPayOrderInfo(vo, goldCoinProductInfo,payAmount, ipAddr, appAccountToken,1);
        } else {
            if(!isVipMember) {
                //创建会员商品订单支付记录
                orderId = payOrderInfoService.createGoldCoinPayOrderInfo(vo, goldCoinProductInfo, payAmount, ipAddr, appAccountToken,1);
            } else {
                //苹果支付没有折扣
                if(!"applePay".equals(vo.getPayType())) {
                    //根据会员类型来打折扣
                     payAmount = goldCoinProductInfo.getPrice().multiply(ObjectUtils.isNotEmpty(productInfo) && ObjectUtils.isNotEmpty(productInfo.getPayGoldCoinDiscount()) ?
                            productInfo.getPayGoldCoinDiscount() : transferVipTypeToDiscount(vipMember.getType())).setScale(2, RoundingMode.DOWN);
                }
                orderId = payOrderInfoService.createGoldCoinPayOrderInfo(vo, goldCoinProductInfo, payAmount, ipAddr, appAccountToken,1);
            }
        }
        return orderId;
    }

    /**
     * @description 根据会员类型转折扣
     * @author cwj
     * @param [type]
     * @return java.math.BigDecimal
     * @date @time 2025/3/8 14:59
     **/
    private BigDecimal transferVipTypeToDiscount(Integer type) {
        BigDecimal discount;
        switch(type){
            case 1:
                discount = new BigDecimal("0.95");
                break;
            case 2:
                discount = new BigDecimal("0.85");
                break;
            case 3:
                discount = new BigDecimal("0.8");
                break;
            case 4:
                discount = new BigDecimal("0.9");
                break;
            default:
                discount = new BigDecimal("0.95");
        }
        return discount;
    }


    /**
     * @description 获取请求的App版本信息
     * @author cwj
     * @param [req]
     * @return com.iot08.api.vo.request.VersionVo
     * @date @time 2025/3/8 10:06
     **/
    private VersionVo obtainVersionInfo(HttpServletRequest req) {
        VersionVo versionVo = new VersionVo();
        //请求头数据解析处理
        versionVo.setUserAgent(req.getHeader("user-agent"));
        versionVo.setVersion(req.getHeader("version"));
        return versionVo;
    }

    /**
     * @description 检查App是androw且版本不低于指定版本
     * @author cwj
     * @param [userAgent, version]
     * @return boolean
     * @date @time 2025/3/8 9:57
     **/
    private boolean isAndrowHighVersion(String userAgent, String version) {
        return StringUtils.isNotEmpty(userAgent) && userAgent.contains("Android") && StringTool.compareVersions(version, supportDiscountLowestVersion) >= 0;
    }

    /**
     * @description 检查产品的折扣是否存在且有效
     * @author cwj
     * @param [productInfo, currentTime]
     * @return boolean
     * @date @time 2025/3/8 8:58
     **/
    private boolean checkDiscountExists(BigDecimal disCount,Long discountStartTime,Long discountEndTime) {
        long currentTime = System.currentTimeMillis()/1000;
        return ObjectUtils.isNotEmpty(disCount) &&
                ObjectUtils.isNotEmpty(discountStartTime) &&
                ObjectUtils.isNotEmpty(discountEndTime) &&
                discountStartTime < currentTime && discountEndTime > currentTime;
    }

    /**
     * @description 查询支付状态
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/1/7 11:31
     **/
    public ResponseMap queryPaymentOrderStatus(QueryPaymentStatusReqBodyFormVo vo){
        //查询支付订单信息
        PayOrderInfo payOrderInfo = payOrderInfoService.findById(new ObjectId(vo.getOrderid()));
        if(ObjectUtils.isEmpty(payOrderInfo)){
            return ResponseMap.fail("订单不存在");
        }
        ResponseMap resp= ResponseMap.success();
        int paymentStatus = 0;
        try {
            //检查有没有收到通知
            if ("wechatPay".equals(payOrderInfo.getPaymentMethod())){
                //查询微信支付的支付订单信息
                paymentStatus = querywXPaymentStatus(vo.getOrderid(), payOrderInfo.getOrderStatus(),payOrderInfo.getOrderType());
                if(paymentStatus<0){
                    return ResponseMap.fail("微信支付订单查询失败");
                }
            } else if("alipay".equals(payOrderInfo.getPaymentMethod())){
                //查询支付宝支付订单信息
                paymentStatus = queryAliPaymentStatus(vo, payOrderInfo);
                if(paymentStatus<0){
                    return ResponseMap.fail("支付宝支付订单查询失败");
                }
            }
            resp.put("paymentStatus",paymentStatus);
        }catch (Exception ex){
            log.error("查询支付结果失败，失败原因为：{}",ex.getMessage());
            return ResponseMap.fail();
        }
        return resp;
    }

    /**
     * @description 查询支付宝支付订单信息
     * @author cwj
     * @param [vo, payOrderInfo]
     * @return int
     * @date @time 2025/1/7 18:37
     **/
    private int queryAliPaymentStatus(QueryPaymentStatusReqBodyFormVo vo, PayOrderInfo payOrderInfo) throws AlipayApiException {
        int paymentStatus = -1;
        //查询支付宝支付通知的信息
        AliPayNotifyInfo aliPayNotifyInfo = aliPayNotifyInfoService.queryAliPayNotifyInfoByOutTradeNo(vo.getOrderid(), Constant.ALIPAY_PAY_NOTIFY_TYPE);
        //不为0，说明数据被之前的查询结果更新过，再查也只能是这个结果
        if(ObjectUtils.isNotEmpty(aliPayNotifyInfo) || !payOrderInfo.getOrderStatus().equals(0)){
            paymentStatus = payOrderInfo.getPaymentStatus();
        } else {
            //查询订单信息
            AlipayTradeQueryResponse response = alipayUtil.queryPaymentOrderInfo(vo.getOrderid(),null);
            if(ObjectUtils.isNotEmpty(response)) {
                if(response.isSuccess()){
                    BigDecimal buyerPayAmount = null;
                    BigDecimal receiptAmount = null;
                    if(StringUtils.isNotEmpty(response.getBuyerPayAmount())){
                        buyerPayAmount = new BigDecimal(response.getBuyerPayAmount());
                    }
                    if(StringUtils.isNotEmpty(response.getReceiptAmount())){
                        receiptAmount = new BigDecimal(response.getReceiptAmount());
                    }
                    BigDecimal totalAmount = new BigDecimal(response.getTotalAmount());
                    if("TRADE_SUCCESS".equals(response.getTradeStatus() ) || "TRADE_FINISHED".equals(response.getTradeStatus())){
                        paymentStatus = 1;
                        //更新订单信息
                        updatePayOrderInfo(vo.getOrderid(), response.getTradeNo(),null,
                                buyerPayAmount,totalAmount , receiptAmount, 1, 1, "订单已支付成功",true);
                        //检查订单是购买会员还是购买金币
                        if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                            //更新会员信息
                            vipMemberService.updateVipMemberInfo(vo.getOrderid(), 1);
                        } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                            //更新用户购买的金币信息
                            userGoldCoinService.updateUserGoldCoin(vo.getOrderid(),1);
                        }
                    }else if("WAIT_BUYER_PAY".equals(response.getTradeStatus())){
                        paymentStatus = 0;
                        updatePayOrderInfo(vo.getOrderid(), response.getTradeNo(),null,
                                buyerPayAmount,totalAmount , receiptAmount, 0, 0, "订单支付中",false);
                    }else {
                        paymentStatus = 2;
                        //交易失败或关闭交易
                        updatePayOrderInfo(vo.getOrderid(),response.getTradeNo(), null,
                                buyerPayAmount,totalAmount , receiptAmount, 2, 2, "订单支付失败或已退款关闭",false);
                    }
                } else {
                    if(Constant.ALIPAY_TRACNSACTION_NOT_EXIST_CODE.equals(response.getSubCode())) {
                       paymentStatus = 0;
                    }
                }
            }
        }
        return paymentStatus;
    }

    /**
     * @param [vo, paymentStatus, payOrderInfo]
     * @return int
     * @description 查询微信支付的支付状态
     * @author cwj
     * @date @time 2025/1/7 15:49
     **/
    private int querywXPaymentStatus(String outTradeNo, Integer payOrderInfoStatus, Integer orderType) throws Exception {
        WechatPayNotifyInfo wechatPayNotifyInfo = wechatPayNotifyInfoService.queryWechatPayNotifyInfoByOutTradeNo(outTradeNo,Constant.WECHAT_PAYMENT_NOTIFY_TYPE);
        //支付状态不为0说明被不是通知回调的数据更新过，即被查询订单更新过
        int paymentStatus = -1;
        if(ObjectUtils.isNotEmpty(wechatPayNotifyInfo) || !payOrderInfoStatus.equals(0)){
            paymentStatus = payOrderInfoStatus;
        }else {
            //查询订单信息
            String responseBody = wxPayUtil.queryWxPaymentOrder(outTradeNo);
            if(ObjectUtils.isEmpty(responseBody)){
                return paymentStatus;
            }
            // 解析返回的 JSON 数据
            ObjectMapper objectMapper = new ObjectMapper();
            JSONObject responseJson = objectMapper.readValue(responseBody, JSONObject.class);
            String paymentTime = responseJson.getString("success_time");
            String transactionId = responseJson.getString("transaction_id");
            JSONObject amount = responseJson.getJSONObject("amount");
            BigDecimal total = null;
            BigDecimal payerTotal = null;
            if(ObjectUtils.isNotEmpty(amount)){
                total = amount.getBigDecimal("total");
                if(ObjectUtils.isNotEmpty(total)) {
                    total = total.divide(new BigDecimal(100),2, RoundingMode.DOWN);
                }
                payerTotal =  amount.getBigDecimal("payer_total");
                if(ObjectUtils.isNotEmpty(payerTotal)){
                    payerTotal = payerTotal.divide(new BigDecimal(100),2, RoundingMode.DOWN);
                }
            }
            //根据查询支付发结果更新订单状态
            if("SUCCESS".equals(responseJson.getString("trade_state"))) {
                paymentStatus = 1;
                //更新订单信息
                updatePayOrderInfo(outTradeNo,transactionId,
                        StringUtils.isNotEmpty(paymentTime)?DateUtil.rfc3339FormatDateStr(paymentTime, DateUtil.FORMAT_1):null,
                        payerTotal,total , null, 1, 1, "订单已支付成功",true);
                //检查订单是购买会员还是购买金币
                if(ObjectUtils.isEmpty(orderType) || orderType.equals(0)) {
                    //更新会员信息
                    vipMemberService.updateVipMemberInfo(outTradeNo, 1);
                } else if(ObjectUtils.isNotEmpty(orderType) && orderType.equals(1)) {
                    //更新用户购买的金币信息
                    userGoldCoinService.updateUserGoldCoin(outTradeNo,1);
                }
            } else if("NOTPAY".equals(responseJson.getString("trade_state"))){
                //订单支付中
                paymentStatus = 0;
                updatePayOrderInfo(outTradeNo,transactionId,StringUtils.isNotEmpty(paymentTime)?DateUtil.rfc3339FormatDateStr(paymentTime, DateUtil.FORMAT_1):null,
                        payerTotal,total,null,0,0,"订单支付中",false);
            } else {
                //交易失败或关闭
                paymentStatus = 2;
                updatePayOrderInfo(outTradeNo,transactionId,
                        StringUtils.isNotEmpty(paymentTime)?DateUtil.rfc3339FormatDateStr(paymentTime, DateUtil.FORMAT_1):null,
                        payerTotal, total,null,2,2,"订单支付失败或已退款关闭",false);
            }
        }
        return paymentStatus;
    }


    /**
     * @description 查询ApplePay订单支付信息
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/1/15 17:54
     **/
    public ResponseMap queryApplePayTransactionInfo(ApplePayQueryReqBodyFormVo vo){
        log.info("苹果支付查询订单请求参数{}",vo);
        if(StringUtils.isEmpty(vo.getTransactionId())){
            return ResponseMap.fail("请求参数参数信息缺失，未传支付订单信息");
        }
        //直接查询订单状态信息
        JWSTransactionDecodedPayload jwsTransactionDecodedPayload = applePayUtil.queryAppleTransactionInfo(vo.getTransactionId());
        if(ObjectUtils.isEmpty(jwsTransactionDecodedPayload)) {
            log.info("查询苹果支付订单不存在或交易失败");
            return ResponseMap.fail("Apple Pay支付订单查询失败");
        }
        PayOrderInfo payOrderInfo = null;
        if(StringUtils.isNotEmpty(vo.getOrderid())) {
            //查询订单状态是否已经被更新了，如果被更新了，说明已经通过通知更新了会员信息
            payOrderInfo = payOrderInfoService.findById(new ObjectId(vo.getOrderid()));
            PayOrderInfo payOrderInfo2 = null;
            if(ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload.getAppAccountToken())) {
                payOrderInfo2 = payOrderInfoService.queryPayOrderInfoByAppAccountToken(jwsTransactionDecodedPayload.getAppAccountToken().toString());
            }
            if(ObjectUtils.isEmpty(payOrderInfo) && ObjectUtils.isEmpty(payOrderInfo2)){
                log.info("苹果支付订单未创建");
                return ResponseMap.fail("支付订单不存在或未创建");
            } else if(ObjectUtils.isNotEmpty(payOrderInfo) && ObjectUtils.isNotEmpty(payOrderInfo2)){
                //比对id是否相等，不相等则指定正确的订单
                if(!payOrderInfo.getId().equals(payOrderInfo2.getId())){
                    payOrderInfo = payOrderInfo2;
                }
            } else if(ObjectUtils.isEmpty(payOrderInfo) && ObjectUtils.isNotEmpty(payOrderInfo2)){
                payOrderInfo = payOrderInfo2;
            } else {
                //根据orderid查询订单不是支付订单，且根据appAccountToken没有查询到订单信息，真实订单不存在
                if(ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload.getAppAccountToken())){
                    log.info("苹果支付订单未创建或不存在，以AppAccountToken为条件未查到订单信息");
                    return ResponseMap.fail("支付订单不存在或未创建");
                }
            }
            //先更新订单信息，不管支付成功还是失败，先将支付的transactionId跟订单关联起来
            payOrderInfoService.updatePayOrderTransactionId(payOrderInfo.getId(),vo.getTransactionId());
            //确认订单是就是待支付的订单
           /* if(StringUtils.isNotEmpty(payOrderInfo.getAppAccountToken()) && ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload.getAppAccountToken())) {
                //不相等说明App传的orderId是对应不上的，重新查询订单信息
                if(!payOrderInfo.getAppAccountToken().equals(jwsTransactionDecodedPayload.getAppAccountToken().toString())) {
                    log.info("出现了订单不一致的情况，传参的订单id为：{}，查询订单查到的ApptAccountToken为：{}",vo.getOrderid(),jwsTransactionDecodedPayload.getAppAccountToken());
                    //payOrderInfo = payOrderInfoService.queryPayOrderInfoByAppAccountToken(jwsTransactionDecodedPayload.getAppAccountToken().toString());
                    //先更新订单信息，不管支付成功还是失败，先将支付的transactionId跟订单关联起来
                    payOrderInfoService.updatePayOrderTransactionId(vo.getOrderid(),"");
                    if(ObjectUtils.isEmpty(payOrderInfo)){
                        log.info("苹果支付订单未创建");
                        return ResponseMap.fail("支付订单不存在或未创建");
                    }
                }
            }*/
        } else {
            //漏传orderid则根据appAccountToken来查询订单信息
            if(ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload.getAppAccountToken())) {
                log.info("appAccountToken为{}",jwsTransactionDecodedPayload.getAppAccountToken());
                payOrderInfo = payOrderInfoService.queryPayOrderInfoByAppAccountToken(jwsTransactionDecodedPayload.getAppAccountToken().toString());
                if(ObjectUtils.isNotEmpty(payOrderInfo)) {
                    payOrderInfoService.updatePayOrderTransactionId(payOrderInfo.getId(),vo.getTransactionId());
                }
            }
            if(ObjectUtils.isEmpty(payOrderInfo)) {
                log.info("苹果支付订单未创建，未查到订单信息或参数未传orderid，且支付时未设置appAccountToken");
                return ResponseMap.fail("支付订单不存在或未创建");
            }
        }
        Long purchaseDate = jwsTransactionDecodedPayload.getPurchaseDate();
        String purchaseDateStr = null;
        if(ObjectUtils.isNotEmpty(purchaseDate)) {
            purchaseDateStr = DateUtil.stampToDateStr(purchaseDate,DateUtil.FORMAT_1);
        }
        boolean isApplePaySuccess = isApplePaySuccessfully(jwsTransactionDecodedPayload);
        log.info("苹果支付订单是否支付成功：{}",isApplePaySuccess);
        //判断订单是否支付成功，判断订单信息是否存在，判断订单是否为未支付
        if(isApplePaySuccess){
            if(ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(0)){
                //说明订单支付成功，更新订单信息和会员信息
                updatePayOrderInfo(payOrderInfo.getId(),jwsTransactionDecodedPayload.getTransactionId(),
                        purchaseDateStr, null,null , null, 1, 1, "订单已支付成功",true);
                //检查订单是购买会员还是购买金币
                if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                    //更新会员信息
                    vipMemberService.updateVipMemberInfo(payOrderInfo.getId(), 1);
                } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                    //更新用户购买的金币信息
                    userGoldCoinService.updateUserGoldCoin(vo.getOrderid(),1);
                }
            }
        } else {
            if(ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload.getRevocationDate()) && ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(0)){
                //订单支付失败，更新订单信息
                updatePayOrderInfo(payOrderInfo.getId(),jwsTransactionDecodedPayload.getTransactionId(),
                        purchaseDateStr, null,null , null, 2, 2, "订单支付失败或已退款关闭",false);
            }
        }
        ResponseMap res = ResponseMap.success();
        if(isApplePaySuccess){
            res.put("paymentStatus",1);
        } else {
            res.put("paymentStatus",0);
        }
        return res;
    }


    /**
     * @description
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/2/17 10:42
     **/
    public ResponseMap queryApplePayHistoryTransactionInfo(ApplePayQueryHistoryReqBodyFormVo vo){
        log.info("苹果支付查询订单请求参数{}",vo);
        //直接查询订单状态信息
        List<JWSTransactionDecodedPayload> jwsTransactionDecodedPayloads = applePayUtil.queryAppleHistoryTransactionInfo(vo.getTransactionId(),new TransactionHistoryRequest());
        if (CollectionUtils.isEmpty(jwsTransactionDecodedPayloads)) {
            log.info("查询苹果支付订单失败");
            return ResponseMap.fail("查询Apple Pay支付订单查询失败");
        }
        ResponseMap res = ResponseMap.success();
        res.put("jwsTransactionDecodedPayloads",jwsTransactionDecodedPayloads);
        return res;
    }


    /**
     * @description 判断订单支付情况
     * @author cwj
     * @param [jtdp]
     * @return boolean
     * @date @time 2025/2/15 17:20
     **/
    public boolean isApplePaySuccessfully(JWSTransactionDecodedPayload jtdp) {
        // 交易 ID 存在、购买时间存在、未退款、订单已购买、 交易类型是购买
        return !StringUtils.isEmpty(jtdp.getTransactionId())
                && ObjectUtils.isNotEmpty(jtdp.getPurchaseDate())
                && jtdp.getRevocationReason() == null
                && "PURCHASED".equals(jtdp.getInAppOwnershipType().getValue())
                && "PURCHASE".equals(jtdp.getTransactionReason().getValue());
    }


    /**
     * @param outTradeNo
     * @param price
     * @time: 2021/2/27 18:12
     * @author: Rock
     * @version 1.0
     */
   /* public void paymentCallBack(String outTradeNo, BigDecimal price, String openid, String subscribe) {
        Payment payment = paymentService.findOne(new Query(Criteria.where("out_trade_no").is(outTradeNo)));
        if (payment != null && (payment.getStatus() == null || Const.INT_0.equals(payment.getStatus()))) {
            Update update = new Update();
            update.set("time", DateUtil.nowTimestampToDouble());
            update.set("price", price.doubleValue());
            update.set("status", 1);
            if (StringUtil.isNotBlank(openid)) {
                update.set("openid", openid);
            }
            if (StringUtil.isNotBlank(subscribe)) {
                update.set("is_subscribe", subscribe);
            }
            paymentService.updateById(payment.getId(), update);

            Device device = deviceService.findById(payment.getImei());
            if (device != null && StringUtil.isNotBlank(payment.getOrderid())) {
                Update updateDevice = new Update();
                if (Integer.parseInt(payment.getOrderid()) == orderIdJuphoon) {
                    updateDevice.set("video_permanent", 1);
                    deviceService.updateById(device.getId(), updateDevice);
                    log.info("设备：{}充值成功，开通永久视频功能", payment.getImei());
                } else if (payment.getOrderid().length() <= 2 && commonProperties.getRenew().size() > Integer.parseInt(payment.getOrderid())) {
                    int minute = Integer.parseInt(commonProperties.getRenew().get(Integer.parseInt(payment.getOrderid())).get("minute").toString());
                    int videoEndtime = device.getVideoEndtime() == null ? 30 : device.getVideoEndtime();
                    updateDevice.set("video_endtime", videoEndtime + minute);
                    deviceService.updateById(device.getId(), updateDevice);
                    log.info("设备：{}充值成功，添加{}分钟, 共{}分钟", payment.getImei(), minute, minute + videoEndtime);
                } else {
                    log.error("payment orderid is exception. payment={}", payment.toString());
                }
            }
        }
    }*/

    /**
     * @description 处理支付回调
     * @author cwj
     * @param [params]
     * @return java.lang.String
     * @date @time 2024/12/30 10:16
     **/
    public String alipayPaymentCallBack(Map<String, String> params) throws AlipayApiException {
        if(CollectionUtils.isEmpty(params)){
            log.error("支付宝异步回调异常！params={}", params);
            return alipayNotifyFail;
        }
        boolean isCheckSign = alipayUtil.notifyParamSignVerify(params);
        AliPayNotifyInfo aliPayNotifyInfo;
        JSONObject jsonObject;
        boolean beforeHasReceivedNotify;
        String tradeStatus = "";
        if(!isCheckSign){
            log.error("支付宝异步回调异常！params={}", params);
            return alipayNotifyFail;
        } else {
            tradeStatus = new String(params.get("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            //保存阿里云通知信息
            jsonObject = aliPayNotifyInfoService.saveOrUpdateNotifyInfo(params,tradeStatus);
            aliPayNotifyInfo = jsonObject.getObject("aliPayNotifyInfo",AliPayNotifyInfo.class);
            beforeHasReceivedNotify = jsonObject.getBooleanValue("beforeHasReceivedNotify");
        }
        //查询支付订单信息
        PayOrderInfo payOrderInfo = payOrderInfoService.findById(new ObjectId(aliPayNotifyInfo.getOutTradeNo()));
        //检查退款通知的类型，如果是支付通知
        if(Constant.ALIPAY_PAY_NOTIFY_TYPE.equals(aliPayNotifyInfo.getAlipayNotifyType())) {
            log.info("支付宝异步回调通知的类型为支付通知......");
            //订单是待支付时，才可以更新记录，避免已经支付的订单更新数据
            if(ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(0)) {
                // 验签，判断是否为支付宝发来的异步通知
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    //更新支付订单信息
                    updatePayOrderInfo(aliPayNotifyInfo.getOutTradeNo(),aliPayNotifyInfo.getTradeNo(),aliPayNotifyInfo.getGmtPayment(),aliPayNotifyInfo.getBuyerPayAmount(),
                            aliPayNotifyInfo.getTotalAmount(),aliPayNotifyInfo.getReceiptAmount(),1,1,"订单已支付成功",true);
                    //检查订单是购买会员还是购买金币
                    if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                        //更新会员信息并保存碎屏险信息
                        vipMemberService.updateVipMemberInfo(aliPayNotifyInfo.getOutTradeNo(), 1);
                    } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                        //更新用户购买的金币信息
                        userGoldCoinService.updateUserGoldCoin(aliPayNotifyInfo.getOutTradeNo(),1);
                    }
                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)){
                    updatePayOrderInfo(aliPayNotifyInfo.getOutTradeNo(),aliPayNotifyInfo.getTradeNo(),aliPayNotifyInfo.getGmtPayment(),aliPayNotifyInfo.getBuyerPayAmount(),
                            aliPayNotifyInfo.getTotalAmount(),aliPayNotifyInfo.getReceiptAmount(),0,0,"订单支付中",false);
                } else {
                    //支付失败，更新支付订单信息
                    updatePayOrderInfo(aliPayNotifyInfo.getOutTradeNo(),aliPayNotifyInfo.getTradeNo(),aliPayNotifyInfo.getGmtPayment(),aliPayNotifyInfo.getBuyerPayAmount(),
                            aliPayNotifyInfo.getTotalAmount(),aliPayNotifyInfo.getReceiptAmount(),2,2,"订单支付失败或已退款关闭",false);
                }
            }
        } else if(Constant.ALIPAY_REFUND_NOTIFY_TYPE.equals(aliPayNotifyInfo.getAlipayNotifyType())) {
            log.info("支付宝异步回调通知的类型为退款通知......");
            //检查是否已经收到过成功的通知，未收到成功的通知，则进行退款订单更新、订单更新以及会员信息更新，如果有收到过成功的信息，则说明信息早就更新过
            if(!beforeHasReceivedNotify){
                //退款通知，通知退款申请成功
                if ("TRADE_CLOSED".equals(tradeStatus)) {
                    //更新退款申请订单的状态
                    refundApplyService.updateRefundApplyByAliPayNotify(aliPayNotifyInfo,"SUCCESS");
                    //退款成功后，更新支付订单、会员的信息
                    updateRefundOrderVipMemberInfo(payOrderInfo);
                }
            }
        }
        return alipayNotifySuccess;
    }

    /**
     * @description 支付宝退款通知
     * @author cwj
     * @param [params]
     * @return java.lang.String
     * @date @time 2025/2/7 11:50
     **/
    public String alipayRefundCallBack(Map<String, String> params) throws AlipayApiException {
        if(CollectionUtils.isEmpty(params)){
            log.error("支付宝退款回调异常！params={}", params);
            return alipayNotifyFail;
        }
        boolean isCheckSign = alipayUtil.notifyParamSignVerify(params);
        AliPayNotifyInfo aliPayNotifyInfo;
        JSONObject jsonObject;
        boolean beforeHasReceivedNotify;
        String tradeStatus = "";
        if(!isCheckSign){
            log.error("支付宝退款回调异常！params={}", params);
            return alipayNotifyFail;
        } else {
            tradeStatus = new String(params.get("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            //保存阿里云通知信息
            jsonObject = aliPayNotifyInfoService.saveOrUpdateNotifyInfo(params,tradeStatus);
            aliPayNotifyInfo = jsonObject.getObject("aliPayNotifyInfo",AliPayNotifyInfo.class);
            beforeHasReceivedNotify = jsonObject.getBooleanValue("beforeHasReceivedNotify");
        }
        //检查是否已经收到过成功的通知，未收到成功的通知，则进行退款订单更新、订单更新以及会员信息更新，如果有收到过成功的信息，则说明信息早就更新过
        if(!beforeHasReceivedNotify) {
            //查询支付订单信息
            PayOrderInfo payOrderInfo = payOrderInfoService.findById(new ObjectId(aliPayNotifyInfo.getOutTradeNo()));
            // 验签，判断是否为支付宝发来的异步通知
            if ("TRADE_CLOSED".equals(tradeStatus)) {
                //更新退款申请订单的状态
                refundApplyService.updateRefundApplyByAliPayNotify(aliPayNotifyInfo, "SUCCESS");
                //退款成功后，更新支付订单、会员的信息
                updateRefundOrderVipMemberInfo(payOrderInfo);
            }
        }
        return alipayNotifySuccess;
    }


    /**
     * @description
     * @author cwj
     * @param [map]
     * @return java.lang.String
     * @date @time 2024/12/31 14:46
     **/
    public String wechatPaymentCallBack(SortedMap<String, String> map){
        String notifyResult = "";
        //
        if ("TRANSACTION.SUCCESS".equals(map.get("event_type"))) {
            //支付成功，处理购买业务
            String outTradeNo = map.get("out_trade_no");
            String openid = map.get("openid");
            String subscribe = map.get("is_subscribe");
            BigDecimal price = new BigDecimal(map.get("total_fee"));

            // 业务处理end
            notifyResult = XMLUtil.setXML(SUCCESS, "OK");
            /*if(SUCCESS.equals(map.get("return_code"))){
                if (SUCCESS.equals(map.get("result_code"))) {
                    String outTradeNo = map.get("out_trade_no");
                    String openid = map.get("openid");
                    String subscribe = map.get("is_subscribe");
                    BigDecimal price = new BigDecimal(map.get("total_fee"));
                    //payService.paymentCallBack(outTradeNo, price, openid, subscribe);
                     notifyResult = XMLUtil.setXML(SUCCESS, "OK");
                } else {
                    // 业务处理end
                    notifyResult = XMLUtil.setXML("FAIL", "fail");
                }
            }*/

        } else {
            // 业务处理end
            notifyResult = XMLUtil.setXML(FAIL, "FAIL");
        }
        return notifyResult;
    }


    /**
     * @description 微信支付回调
     * @author cwj
     * @param [serialNo, signature, timestamp, nonceStr, requestBody]
     * @return java.lang.String
     * @date @time 2025/1/4 9:22
     **/
    public String wechatPaymentCallBack(String serialNo, String signature, String timestamp, String nonceStr, String requestBody, HttpServletResponse response) {
        try{
            log.info("微信支付回调通知......");
            //比对平台证书的序列号
            String result = verifyNotifyData(serialNo, signature, timestamp, nonceStr, requestBody, response);
            if (result != null) return result;
            //检查之前是否已经成功收到通知
            //构建微信支付通知信息
            JSONObject jsonObject = wechatPayNotifyInfoService.saveOrUpdateNotifyInfo(requestBody,Constant.WECHAT_PAYMENT_NOTIFY_TYPE);
            WechatPayNotifyInfo wechatPayNotifyInfo = jsonObject.getObject("wechatPayNotifyInfo",WechatPayNotifyInfo.class);
            //是否之前已经接收到了支付成功的通知
            boolean beforeHasReceived = jsonObject.getBooleanValue("beforeHasReceived");
            //查询支付订单信息
            PayOrderInfo payOrderInfo = payOrderInfoService.findById(new ObjectId(wechatPayNotifyInfo.getOutTradeNo()));
            if(!beforeHasReceived && ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(0)) {
                //支付成功，更新订单和会员信息
                if("SUCCESS".equals(wechatPayNotifyInfo.getTradeStatus())){
                    updatePayOrderInfo(wechatPayNotifyInfo.getOutTradeNo(),wechatPayNotifyInfo.getTransactionId(),wechatPayNotifyInfo.getSuccessTime(),wechatPayNotifyInfo.getPayerTotal(),
                            wechatPayNotifyInfo.getTotal(),null,1,1,"订单已支付成功",true);
                    //检查订单是购买会员还是购买金币
                    if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                        //更新会员信息并保存碎屏险信息
                        vipMemberService.updateVipMemberInfo(wechatPayNotifyInfo.getOutTradeNo(), 1);
                    } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                        //更新用户购买的金币信息
                        userGoldCoinService.updateUserGoldCoin(wechatPayNotifyInfo.getOutTradeNo(),1);
                    }
                } else if ("NOTPAY".equals(wechatPayNotifyInfo.getTradeStatus())){
                    updatePayOrderInfo(wechatPayNotifyInfo.getOutTradeNo(),wechatPayNotifyInfo.getTransactionId(),wechatPayNotifyInfo.getSuccessTime(),wechatPayNotifyInfo.getPayerTotal(),
                            wechatPayNotifyInfo.getTotal(),null,0,0,"订单支付中",false);
                } else {
                    //交易关闭或支付失败
                    updatePayOrderInfo(wechatPayNotifyInfo.getOutTradeNo(),wechatPayNotifyInfo.getTransactionId(),wechatPayNotifyInfo.getSuccessTime(),wechatPayNotifyInfo.getPayerTotal(),
                            wechatPayNotifyInfo.getTotal(),null,2,2,"订单支付失败或已退款关闭",false);
                }
            }
            //业务处理
            response.setStatus(200);
            return assembleReturnString(SUCCESS,"成功");
        }catch (Exception e){
            log.error("微信回调通知发生异常，异常信息为：{}",e.getMessage());
            response.setStatus(500);
            return assembleReturnString("FAIL", "失败");
        }
    }


    /**
     * @description 微信退款回调通知
     * @author cwj
     * @param [serialNo, signature, timestamp, nonceStr, requestBody, response]
     * @return java.lang.String
     * @date @time 2025/2/8 14:49
     **/
    public String wechatRefundCallBack(String serialNo, String signature, String timestamp, String nonceStr, String requestBody, HttpServletResponse response) {
        try{
            log.info("微信退款回调通知......");
            //比对平台证书的序列号
            String result = verifyNotifyData(serialNo, signature, timestamp, nonceStr, requestBody, response);
            if (result != null) return result;
            //构建微信支付通知信息
            JSONObject jsonObject = wechatPayNotifyInfoService.saveOrUpdateNotifyInfo(requestBody,Constant.WECHAT_REFUND_NOTIFY_TYPE);
            WechatPayNotifyInfo wechatPayNotifyInfo = jsonObject.getObject("wechatPayNotifyInfo",WechatPayNotifyInfo.class);
            //是否之前已经成功接收了通知
            boolean beforeHasReceived = jsonObject.getBooleanValue("beforeHasReceived");
            //查询支付订单信息
            PayOrderInfo payOrderInfo = payOrderInfoService.findById(new ObjectId(wechatPayNotifyInfo.getOutTradeNo()));
            if(!beforeHasReceived){
                //更新退款申请订单的状态
                refundApplyService.updateRefundApplyByWechatNotify(wechatPayNotifyInfo,wechatPayNotifyInfo.getTradeStatus());
                //退款成功，更新订单和会员信息
                if("SUCCESS".equals(wechatPayNotifyInfo.getTradeStatus())){
                    //更新会员、订单的信息
                    updateRefundOrderVipMemberInfo(payOrderInfo);
                }
            }
            //业务处理
            response.setStatus(200);
            return assembleReturnString(SUCCESS,"成功");
        }catch (Exception e){
            log.error("微信回调通知发生异常，异常信息为：{}",e.getMessage());
            response.setStatus(500);
            return assembleReturnString("FAIL", "失败");
        }
    }

    /**
     * @description 退款后更新支付订单、会员等的状态信息
     * @author cwj
     * @param [outTradeNo,isOrderPaid]
     * @return void
     * @date @time 2025/2/19 17:20
     **/
    private void updateRefundOrderVipMemberInfo(PayOrderInfo payOrderInfo) {
        log.info("退款后更新支付订单及会员等的状态信息");
        //检查订单是否已支付，已支付的情况才能更新为退款状态，防止接收到多次通知后多次更新数据
        if(ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(1)) {
            //更新支付订单状态为退款状态
            payOrderInfoService.updatePayOrderRefundStatus(payOrderInfo.getId(),3,3);
            PayOrderInfo secondPayOrderInfo;
            //检查订单是购买会员还是购买金币
            if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                //查询会员信息，有效无效都查询
                VipMember vipMember = vipMemberService.queryVipMemberByOpenId(payOrderInfo.getOpenid());
                if(ObjectUtils.isNotEmpty(vipMember)) {
                    //退款订单是否为最后购买服务的订单
                    if(payOrderInfo.getId().equals(vipMember.getOrderid())){
                        //log.info("查询倒数第二个支付订单信息之前");
                        //查询倒数第二个有效支付订单信息，如果存在，则将会员的订单信息更新为倒数第二个的订单信息
                        secondPayOrderInfo = payOrderInfoService.queryInverseSecondPayOrderInfo(payOrderInfo.getOpenid(),payOrderInfo.getId());
                        log.info("查询倒数第二个支付订单信息之后，secondPayOrderInfo的数据为：{}",secondPayOrderInfo);
                        //根据订单对应的产品类型，更新会员的有效期
                        vipMemberService.updateVipMemberEffectTimeTypeOrderId(vipMember,payOrderInfo.getProductType(),
                                !ObjectUtils.isEmpty(secondPayOrderInfo),!ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getId():null,
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getProductType():null);
                        //取消之前买会员时赠送的碎屏险
                        brokenScreenInsuranceService.updateBrokenScreenInsuranceStatus(payOrderInfo.getId(),payOrderInfo.getOpenid(),4);
                    } else {
                        vipMemberService.updateVipMemberEffectTimeTypeOrderId(vipMember,payOrderInfo.getProductType()
                                ,false,null,null);
                        //取消之前买会员时赠送的碎屏险
                        brokenScreenInsuranceService.updateBrokenScreenInsuranceStatus(payOrderInfo.getId(),payOrderInfo.getOpenid(),4);
                    }
                }
            } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                //更新用户购买的金币信息，有效无效都查询
                UserGoldCoin userGoldCoin = userGoldCoinService.queryUserGoldCoinByOpenId(payOrderInfo.getOpenid());
                if(ObjectUtils.isNotEmpty(userGoldCoin)){
                    if(payOrderInfo.getId().equals(userGoldCoin.getOrderid())) {
                        log.info("查询倒数第二个支付订单信息之前");
                        //查询倒数第二个有效支付订单信息，如果存在，则将会员的订单信息更新为倒数第二个的订单信息
                        secondPayOrderInfo = payOrderInfoService.queryInverseSecondPayOrderInfo(payOrderInfo.getOpenid(), payOrderInfo.getId());
                        log.info("查询倒数第二个支付订单信息之后，secondPayOrderInfo的数据为：{}",secondPayOrderInfo);
                        userGoldCoinService.updateUserGoldCoinNum(userGoldCoin,payOrderInfo.getGoldCoinNum(),
                                !ObjectUtils.isEmpty(secondPayOrderInfo),
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getGoldCoinNum():null,
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getId():null,
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getProductType():null);
                    } else {
                        userGoldCoinService.updateUserGoldCoinNum(userGoldCoin,payOrderInfo.getGoldCoinNum(),false,null,null,null);
                    }
                }
            }
        }

    }

    /**
     * @description 验证异步回调通知的证书及签名信息
     * @author cwj
     * @param [serialNo, signature, timestamp, nonceStr, requestBody, response]
     * @return java.lang.String
     * @date @time 2025/2/8 15:00
     **/
    private String verifyNotifyData(String serialNo, String signature, String timestamp, String nonceStr, String requestBody, HttpServletResponse response) throws Exception {
        String result = comparePlatformSerialNo(serialNo, response);
        if (result != null) return result;
        //组装验签字符串
        String signStr = WeChatPayUtils.buildPayNotifySignString(timestamp, nonceStr, requestBody);
        log.info("回调签名字符串为：{}",signStr);
        //验证签名
        boolean isValid = wxPayUtil.verifySignature(signature, signStr);
        if(!isValid) {
            log.error("微信退款通知签名验证失败签名验证失败");
            response.setStatus(500);
            return assembleReturnString("FAIL", "失败");
        }
        return null;
    }

    /**
     * @description 比对微信商户证书
     * @author cwj
     * @param [serialNo, response]
     * @return java.lang.String
     * @date @time 2025/2/8 14:59
     **/
    private String comparePlatformSerialNo(String serialNo, HttpServletResponse response) {
        if(!wxPayUtil.comparePlatformCertSerialNo(serialNo)){
            response.setStatus(500);
            return assembleReturnString(FAIL, "失败");
        }
        return null;
    }


    /**
     * @description Apple pay回调通知
     * @author cwj
     * @param [responseBodyV2]
     * @return org.springframework.http.ResponseEntity<java.lang.String>
     * @date @time 2025/1/13 14:53
     **/
    public ResponseEntity<String> applePaymentCallBack(ResponseBodyV2 responseBodyV2){
        ResponseBodyV2DecodedPayload responseBodyV2DecodedPayload = applePayUtil.verifyAndDecodeNotification(responseBodyV2);
        log.info("验签和解密后的数据为：{}",responseBodyV2DecodedPayload);
        if(ObjectUtils.isEmpty(responseBodyV2DecodedPayload)){
            return ResponseEntity.status(400).body("Invalid notification signature");
        } else {
            if(!ObjectUtils.isEmpty(responseBodyV2DecodedPayload.getData())){
                //接着解密
                JWSTransactionDecodedPayload  jwsTransactionDecodedPayload = applePayUtil.verifyAndDecodeTransaction(responseBodyV2DecodedPayload.getData().getSignedTransactionInfo());
                log.info("解密后的订单信息为：{}",jwsTransactionDecodedPayload);
                JWSRenewalInfoDecodedPayload jwsRenewalInfoDecodedPayload = applePayUtil.verifyAndDecodeRenewalInfo(responseBodyV2DecodedPayload.getData().getSignedRenewalInfo());
                log.info("自动续订的数据信息为：{}",jwsRenewalInfoDecodedPayload);
                //保存回调通知记录
                applePayNotifyInfoService.saveOrUpdateApplePayNotifyInfoByResponseBody(responseBodyV2DecodedPayload,jwsTransactionDecodedPayload,jwsRenewalInfoDecodedPayload);
                log.info("保存通知记录");
                String notifyType = responseBodyV2DecodedPayload.getNotificationType().getValue();
                if(ObjectUtils.isNotEmpty(jwsTransactionDecodedPayload)){
                    //查询订单信息
                    PayOrderInfo payOrderInfo = payOrderInfoService.queryPayOrderInfoByTransactionId(jwsTransactionDecodedPayload.getTransactionId());
                    //如果是付款通知
                    if(NotificationTypeV2.SUBSCRIBED.getValue().equals(notifyType)){
                        //订单状态未更新,说明订单存在，但订单状态未更新
                        if(ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(0)) {
                            Long purchaseDate = jwsTransactionDecodedPayload.getPurchaseDate();
                            String purchaseDateStr = null;
                            if(ObjectUtils.isNotEmpty(purchaseDate)) {
                                purchaseDateStr = DateUtil.stampToDateStr(purchaseDate,DateUtil.FORMAT_1);
                            }
                            log.info("接收到苹果支付通知记录，更新支付订单信息");
                            updatePayOrderInfo(payOrderInfo.getId(),jwsTransactionDecodedPayload.getTransactionId(),purchaseDateStr,null,
                                    null,null,1,1,"订单已支付成功",true);
                            if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                                //更新会员信息并保存碎屏险信息
                                vipMemberService.updateVipMemberInfo(payOrderInfo.getId(), 1);
                            } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                                //更新用户购买的金币信息
                                userGoldCoinService.updateUserGoldCoin(payOrderInfo.getId(),1);
                            }
                        }
                    } else if(NotificationTypeV2.REFUND.getValue().equals(notifyType)){
                        //退款申请成功
                        log.info("退款后更新支付订单及会员等的状态信息");
                        refundUpdatePayOrderVipMember(payOrderInfo);
                    }
                }
            }
            return ResponseEntity.ok("Payment success");
        }
    }

    /**
     * @description 退款后更新支付订单状态信息、更新会员数据信息、更新碎屏险信息
     * @author cwj
     * @param [payOrderInfo]
     * @return void
     * @date @time 2025/2/24 10:06
     **/
    private void refundUpdatePayOrderVipMember(PayOrderInfo payOrderInfo) {
        //订单存在且订单目前为已支付
        if(ObjectUtils.isNotEmpty(payOrderInfo) && payOrderInfo.getOrderStatus().equals(1)) {
            //更新支付订单状态为退款状态
            payOrderInfoService.updatePayOrderRefundStatus(payOrderInfo.getId(),3,3);
            PayOrderInfo secondPayOrderInfo;
            //检查订单是购买会员还是购买金币
            if(ObjectUtils.isEmpty(payOrderInfo.getOrderType()) || payOrderInfo.getOrderType().equals(0)) {
                //查询会员信息，有效无效都查询
                VipMember vipMember = vipMemberService.queryVipMemberByOpenId(payOrderInfo.getOpenid());
                if (payOrderInfo.getId().equals(vipMember.getOrderid())) {
                    log.info("查询倒数第二个支付订单信息之前");
                    //查询倒数第二个有效支付订单信息，如果存在，则将会员的订单信息更新为倒数第二个的订单信息
                    secondPayOrderInfo = payOrderInfoService.queryInverseSecondPayOrderInfo(payOrderInfo.getOpenid(), payOrderInfo.getId());
                    log.info("查询倒数第二个支付订单信息之后，secondPayOrderInfo的数据为：{}", secondPayOrderInfo);
                    //根据订单对应的产品类型，更新会员的有效期
                    vipMemberService.updateVipMemberEffectTimeTypeOrderId(vipMember, payOrderInfo.getProductType(),
                            !ObjectUtils.isEmpty(secondPayOrderInfo), !ObjectUtils.isEmpty(secondPayOrderInfo) ? secondPayOrderInfo.getId() : null,
                            !ObjectUtils.isEmpty(secondPayOrderInfo) ? secondPayOrderInfo.getProductType() : null);
                    //取消之前买会员时赠送的碎屏险
                    brokenScreenInsuranceService.updateBrokenScreenInsuranceStatus(payOrderInfo.getId(),payOrderInfo.getOpenid(),4);
                } else {
                    vipMemberService.updateVipMemberEffectTimeTypeOrderId(vipMember, payOrderInfo.getProductType()
                            , false, null, null);
                    //取消之前买会员时赠送的碎屏险
                    brokenScreenInsuranceService.updateBrokenScreenInsuranceStatus(payOrderInfo.getId(),payOrderInfo.getOpenid(),4);
                }
            } else if(ObjectUtils.isNotEmpty(payOrderInfo.getOrderType()) && payOrderInfo.getOrderType().equals(1)) {
                //更新用户购买的金币信息，有效无效都查询
                UserGoldCoin userGoldCoin = userGoldCoinService.queryUserGoldCoinByOpenId(payOrderInfo.getOpenid());
                if(ObjectUtils.isNotEmpty(userGoldCoin)){
                    if(payOrderInfo.getId().equals(userGoldCoin.getOrderid())) {
                        log.info("查询倒数第二个支付订单信息之前");
                        //查询倒数第二个有效支付订单信息，如果存在，则将会员的订单信息更新为倒数第二个的订单信息
                        secondPayOrderInfo = payOrderInfoService.queryInverseSecondPayOrderInfo(payOrderInfo.getOpenid(), payOrderInfo.getId());
                        log.info("查询倒数第二个支付订单信息之后，secondPayOrderInfo的数据为：{}",secondPayOrderInfo);
                        userGoldCoinService.updateUserGoldCoinNum(userGoldCoin,payOrderInfo.getGoldCoinNum(),
                                !ObjectUtils.isEmpty(secondPayOrderInfo),
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getGoldCoinNum():null,
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getId():null,
                                !ObjectUtils.isEmpty(secondPayOrderInfo)?secondPayOrderInfo.getProductType():null);
                    } else {
                        userGoldCoinService.updateUserGoldCoinNum(userGoldCoin,payOrderInfo.getGoldCoinNum(),false,null,null,null);
                    }
                }
            }
        }
    }


    /**
     * @description
     * @author cwj
     * @param [code, msg]
     * @return java.lang.String
     * @date @time 2025/1/4 9:55
     **/
    private String assembleReturnString(String code, String msg) {
        return "{" +
                '"' + "code" + '"' + ":" + '"' + code + '"' + " " +
                '"' + "message" + '"' + ":" + '"' + msg + '"' +
                "}";
    }

    /**
     * @description 更新支付订单信息
     * @author cwj
     * @param [aliPayNotifyInfo]
     * @return void
     * @date @time 2024/12/30 14:19
     **/
    private void updatePayOrderInfo(String outTradeNo,String transactionId,String paymentTime,BigDecimal realPayment,BigDecimal totalAmount,BigDecimal realReceiptAmount,
                                    Integer orderStatus,Integer paymentStatus,String remark,boolean isPaySuccess) {
        PayOrderInfoUpdateVo order = new PayOrderInfoUpdateVo();
        order.setOrderid(outTradeNo);
        order.setTransactionId(transactionId);
        order.setOrderStatus(orderStatus);
        //成功支付了才有支付时间
        if(isPaySuccess){
            //设置支付时间
            order.setPaymentTime(StringUtils.isNotEmpty(paymentTime) ? paymentTime:DateUtil.dateToStr(DateUtil.getDate(new Date()),DateUtil.FORMAT_1));
        }
        //设置支付
        if(ObjectUtils.isNotEmpty(totalAmount)) {
            log.info("totalAmount的值为：{}：",totalAmount);
            order.setPayAmount(totalAmount);
        }
        //设置实际付款金额，不存在则为订单金额
        if(ObjectUtils.isNotEmpty(realPayment)){
            order.setRealPayAmount(realPayment);
        }

        if(ObjectUtils.isNotEmpty(realReceiptAmount)){
            order.setRealReceiptAmount(realReceiptAmount);
        }
        order.setPaymentStatus(paymentStatus);
        order.setRemark(remark);
        payOrderInfoService.updatePayOrderInfo(order);
    }
}
